//
//  BookDBManager.m
//  readNovels
//
//  Created by wulanzhou on 2017/2/27.
//  Copyright © 2017年 wulanzhou. All rights reserved.
//

#import "BookDBManager.h"
#import "CZFilesOperatoion.h"
#import "BSQLConfig.h"
#import <FMDB/FMDB.h>
#import <MJExtension/MJExtension.h>

@interface BookDBManager ()
@property(nonatomic,strong) FMDatabaseQueue *userDBQueue;
@property(nonatomic,strong) NSString *dbPath;
@end

@implementation BookDBManager

+ (BookDBManager *)shareInstance
{
    static dispatch_once_t  onceToken;
    static BookDBManager * sSharedInstance;
    
    dispatch_once(&onceToken, ^{
        sSharedInstance = [[BookDBManager alloc] init];
    });
    return sSharedInstance;
}

- (instancetype)init{

    if (self = [super init]) {
        NSString *savePath = [[CZFilesOperatoion getFilePathWithType:FileDirectoryDocumentType] stringByAppendingPathComponent:@"db"];
        [CZFilesOperatoion createDirectoryWithPath:savePath];
        self.dbPath = savePath;
        
        NSLog(@"db Path = %@",self.dbPath);
    }
    return self;
}


- (BOOL)createDBWithName:(NSString *)name{
    
    NSArray *sqlList = [NSArray arrayWithObjects:book_table_sql,catalog_table_sql,chapter_table_sql,nil];
    return [self createDBWithName:name tableSqlArray:sqlList];
}
- (BOOL)createDBWithName:(NSString *)name tableSqlArray:(NSArray *)sqlTables{
    @synchronized(self.userDBQueue){
        
        if (0 == [name length])
        {
            NSLog(@"用户ID错误!");
            [self.userDBQueue close];
            self.userDBQueue = nil;
            return NO;
        }
        
        NSString *filePath = [self.dbPath stringByAppendingPathComponent:name];
        NSLog(@"db filePath = %@",filePath);
        self.userDBQueue = [FMDatabaseQueue databaseQueueWithPath:filePath];
        if (self.userDBQueue)
        {
            __block BOOL flag = NO;
            [self.userDBQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
               // NSArray *sqlList = [NSArray arrayWithObjects:book_table_sql,catalog_table_sql,chapter_table_sql,nil];
                for (NSString *sqlStr in sqlTables)
                {
                    flag = [db executeUpdate:sqlStr];
                    if (!flag)
                    {
                        *rollback = YES;
                        break;
                    }
                }
            }];
            
            if (!flag)
            {
                NSLog(@"数据库创建表失败");
            }else{
                NSLog(@"数据库创建表成功");
            }
            
            return flag;
        }
        else
        {
            NSLog(@"用数据库创建失败");
        }
    }
    return NO;
}


- (BOOL)updataDBWithSql:(NSString *)sql, ...NS_REQUIRES_NIL_TERMINATION{

    @synchronized(self.userDBQueue){
    
        if (!self.userDBQueue || 0 == [sql length])
        {
            return NO;
        }
        
        if (!sql) {
            return NO;
        }

        //首先在函数里定义一个va_list型的变量,这里是p_list,这个变量是指向参数的指针.
        va_list args;
        //然后用va_start宏初始化变量p_list.
        va_start(args, sql);
        
        BOOL flag = [self update:sql withVAList:args];
        //清空参数指针，最后用va_end宏结束可变参数的获取。
        va_end(args);
        
        return flag;
    }

}

- (BOOL)transactionUpdataDBWithSqlArray:(NSArray *)sqlArray arguments:(NSArray *)args{


    @synchronized(self.userDBQueue)
    {
        if (!self.userDBQueue || 0 == [sqlArray count])
        {
            return NO;
        }
        
        __block BOOL flag = NO;
        
        [self.userDBQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
            NSInteger index = 0;
            for (NSString *sqlStr in sqlArray)
            {
                if (args && [args count] > 0 && index < [args count]) {
                    flag = [db executeUpdate:sqlStr withArgumentsInArray:args[index]];
                }else{
                    flag = [db executeUpdate:sqlStr];
                }
                if (!flag)
                {
                    //NSLog(@" sqlStr =%@ ,args = %@",sqlStr,args[index]);
                    *rollback = YES;
                    break;
                }
                
                index ++;
            }
        }];
        
        return flag;
    }
}

#pragma mark -查询
- (NSArray *)queryDBWithModels:(Class)cls sql: (NSString *)sql, ...NS_REQUIRES_NIL_TERMINATION{

    //首先在函数里定义一个va_list型的变量,这里是p_list,这个变量是指向参数的指针.
    va_list p_list;
    //然后用va_start宏初始化变量p_list.
    va_start(p_list, sql);
    
    NSArray *rowDicArray = [self queryDBWithSql:sql withVAList:p_list];
    
    //清空参数指针，最后用va_end宏结束可变参数的获取。
    va_end(p_list);
    
    if (rowDicArray && [rowDicArray count]>0) {
        NSMutableArray *resultM = [NSMutableArray array];
        for (NSDictionary *rowDic in rowDicArray) {
            id model = [cls mj_objectWithKeyValues:rowDic];
            [resultM addObject:model];
        }
        
        return resultM;
    }
    return nil;
}
- (NSArray *)queryDBWithSql:(NSString *)sql, ...NS_REQUIRES_NIL_TERMINATION;
{
    //首先在函数里定义一个va_list型的变量,这里是p_list,这个变量是指向参数的指针.
    va_list p_list;
    //然后用va_start宏初始化变量p_list.
    va_start(p_list, sql);
    
    NSArray *source = [self queryDBWithSql:sql withVAList:p_list];
    
    //清空参数指针，最后用va_end宏结束可变参数的获取。
    va_end(p_list);
    return source;
}

- (BOOL)update:(NSString *)sql withVAList:(va_list)args{
    
    __block BOOL flag = NO;
    
    [self.userDBQueue inDatabase:^(FMDatabase *db) {
        flag = [db executeUpdate:sql withVAList:args];
    }];
    
    return flag;
}

- (NSArray *)queryDBWithSql:(NSString *)sql withVAList:(va_list)args{
    @synchronized(self.userDBQueue)
    {
        if (!self.userDBQueue)
        {
            return nil;
        }
        if (!sql) {
            return nil;
        }
        
        __block NSMutableArray *aList = [[NSMutableArray alloc] initWithCapacity:2];
        [self.userDBQueue inDatabase:^(FMDatabase *db) {
            FMResultSet *result = [db executeQuery:sql withVAList:args];
            if (result)
            {
                while ([result next])
                {
                    NSMutableDictionary  *aDict = [[NSMutableDictionary alloc] initWithCapacity:2];
                    NSArray *keyList = [[result columnNameToIndexMap] allKeys];
                    for (NSString *aKey in keyList)
                    {
                        id obj = [result objectForColumnName:aKey];
                        [aDict setObject:obj forKey:aKey];
                    }
                    [aList addObject:aDict];
                }
                [result close];
            }
            
        }];
        return aList;
        
    }

}

@end
